import { Icon, StyledToggleButtonGroup } from '@amcax/base';
import { useNewMark } from '@app-base/common/hooks/useNewMark';
import { nextmeshEventCenter } from '@app-nextmesh/common/events/EventCenter';
import { IToolRadioOption } from '@app-nextmesh/components/types';
import {
  ENTITY_TYPE,
  ENTITY_TYPE_ALL,
  ENTITY_TYPES,
  ModelEventType,
  ModelPickSwitchEvent,
  ModelPickTypesEvent,
  ModelTheme,
} from '@app-nextmesh/types';
import {
  events,
  updateGeometriesVisible,
  updateMeshesVisible,
  updateWireframeVisible,
} from '@app-nextmesh/utils';
import { ToggleButton } from '@mui/material';
import type { MenuProps } from 'antd';
import { Dropdown, notification } from 'antd';
import { useEffect, useState } from 'react';
import Icons from '../../Icons';
import { useModelStore } from '../../store/model';
import RadioGroup from './RadioGroup';
import ToolBarData from './data';
import './style.scss';

/**
 * 模型选取模式RadioButton 组
 */
function ModelPickRadioGroup({
  options,
}: {
  options: Array<IToolRadioOption>;
}) {
  const [opts, setOpts] = useState([...options]);
  const [currentPickType, setCurrentPickType] = useState(ENTITY_TYPE_ALL);
  const [mix, setMix] = useState(false); // 是否混合选择
  // 当前选取主题
  const [modelTheme, setModelTheme] = useState<ModelTheme>(ModelTheme.Default);

  useEffect(() => {
    events.on(ModelEventType.SwitchTheme, modelThemeListener);
    events.on(ModelEventType.PickTypes, typeListener);
    return () => {
      events.off(ModelEventType.SwitchTheme, modelThemeListener);
      events.off(ModelEventType.PickTypes, typeListener);
    };
  }, []);
  useEffect(() => {
    // switchListener 使用到了 mix，所以这里都要重新off/on
    events.on(ModelEventType.SetCurrentPickType, switchListener);
    return () => {
      events.off(ModelEventType.SetCurrentPickType, switchListener);
    };
  }, [mix]);
  const switchListener = (event: ModelPickSwitchEvent) => {
    const eventType = event?.type;
    const newOpts = [...opts];
    newOpts.forEach((opt) => (opt.isActived = opt.value === eventType));
    setOpts([...opts]);
    setCurrentPickType(eventType);
    const pickType = ENTITY_TYPES.indexOf(eventType);
    nextmeshEventCenter().setPickType([pickType], !mix);
  };
  // 根据表单可选取的模式列表，设置选取模式是否禁用
  const typeListener = (event: ModelPickTypesEvent) => {
    const eventTypes = event?.types;
    const newOpts = [...opts];
    newOpts.forEach((opt) => {
      opt.disabled = !eventTypes?.includes(opt.value as ENTITY_TYPE);
      if (event.mix) {
        opt.isActived = false;
      }
    });
    setOpts(newOpts);
    setMix(event.mix);
    const pickTypes = eventTypes?.map((type) => ENTITY_TYPES.indexOf(type));
    nextmeshEventCenter().setPickType(pickTypes, event.mix);
  };
  const modelThemeListener = (theme: ModelTheme) => {
    setModelTheme(theme);
  };
  const getScope = (theme: ModelTheme) => {
    switch (theme) {
      case ModelTheme.Source:
        return 'SOURCE_ASSIGNMENT';
      case ModelTheme.Target:
        return 'TARGET_ASSIGNMENT';
      default:
        return 'SELECTION';
    }
  };
  const handleRadioItemClick = (value: string) => {
    if (currentPickType === value) {
      return;
    }
    setCurrentPickType(value);
    events.emit(ModelEventType.SetCurrentPickType, {
      type: value,
      clear: !mix,
    });
  };
  return (
    <RadioGroup
      options={opts}
      onRadioItemClick={handleRadioItemClick}
      scope={getScope(modelTheme)}
    />
  );
}

function GeometryVisibleGroup() {
  const [visibleEntity, setVisibleEntity] = useState(true);
  // 模型是否加载完成
  const modelStore = useModelStore();

  useEffect(() => {
    events.on(ModelEventType.MeshesData, hideGeometry);
    if (modelStore.loaded) {
      updateWireframeVisible(modelStore.visibleWireframe);
    }
    return () => {
      events.off(ModelEventType.MeshesData, hideGeometry);
    };
  }, [modelStore.loaded, modelStore.visibleWireframe]);

  const hideGeometry = (data) => {
    // 暂时不显/隐Geometry，通过控制Geometry 的 polygon 来解决 闪烁（斑马纹）
    if (Object.keys(data).length !== 0) {
      // updateGeometriesVisible('hide');
      // setVisibleEntity(false);
    }
  };

  const showEntity = (checked: boolean) => {
    setVisibleEntity(checked);
    updateGeometriesVisible(checked ? 'show' : 'hide');
  };

  const items: MenuProps['items'] = [
    {
      key: '1',
      label: (
        <a
          onClick={() => {
            modelStore.setVisibleWireframe(!modelStore.visibleWireframe);
          }}
        >
          {modelStore.visibleWireframe ? '隐藏线框' : '显示线框'}
        </a>
      ),
    },
    {
      key: '2',
      label: (
        <a onClick={() => showEntity(!visibleEntity)}>
          {visibleEntity ? '隐藏几何' : '显示几何'}
        </a>
      ),
    },
  ];
  return (
    <Dropdown
      menu={{ items }}
      placement='bottomLeft'
    >
      <ToggleButton
        value='visibleGeometry'
        size='small'
        title='几何显示/隐藏'
      >
        <Icons name='IconWireframe' />
      </ToggleButton>
    </Dropdown>
  );
}

function MeshVisibleGroup() {
  // 模型是否加载完成
  const modelStore = useModelStore();

  useEffect(() => {
    if (modelStore.loaded) {
      updateWireframeVisible(modelStore.visibleWireframe);
    }
  }, [modelStore.loaded, modelStore.visibleWireframe]);

  const actions: {
    action: 'show' | 'hide' | 'translucence' | 'wireframe';
    label: string;
  }[] = [
    {
      action: 'show',
      label: '显示网格',
    },
    {
      action: 'translucence',
      label: '半透明',
    },
    {
      action: 'wireframe',
      label: '线框',
    },
    {
      action: 'hide',
      label: '隐藏',
    },
  ];
  const items: MenuProps['items'] = actions.map((item) => ({
    key: item.action,
    label: (
      <a
        onClick={() => {
          updateMeshesVisible(item.action);
        }}
      >
        {item.label}
      </a>
    ),
  }));
  return (
    <Dropdown
      menu={{ items }}
      placement='bottomLeft'
    >
      <ToggleButton
        value='visibleMesh'
        size='small'
        title='网格显示/隐藏'
      >
        <Icons name='IconWireframe' />
      </ToggleButton>
    </Dropdown>
  );
}

function CommentSelected() {
  const [newCommentSelected, setNewCommentSelected] = useState(false);

  const { execute, exit } = useNewMark(() => {
    setNewCommentSelected(false);
  });

  const [api, contextHolder] = notification.useNotification({
    placement: 'top',
    top: 80,
    duration: null,
  });
  useEffect(() => {
    if (newCommentSelected) {
      execute();
      api.info({
        message: '选择元素以添加标签',
        closable: false,
        duration: null,
      });
    } else {
      exit();
      api.destroy();
    }
  }, [newCommentSelected]);
  return (
    <>
      <ToggleButton
        value='newMark'
        size='small'
        title='新建标签'
        selected={newCommentSelected}
        onChange={() => {
          setNewCommentSelected(!newCommentSelected);
        }}
      >
        <Icon name='commands/common/mark' />
      </ToggleButton>
      {contextHolder}
    </>
  );
}

export default function ToolBar() {
  const { pickOptions } = ToolBarData;

  return (
    <div className='nm-appFrame__viewerToolbar'>
      <nav className='nm-ViewerToolbar'>
        <ul className='nm-appFrame__viewerToolbarLayout'>
          <StyledToggleButtonGroup>
            <GeometryVisibleGroup />
          </StyledToggleButtonGroup>
          <span className='nm-ViewerToolbar-separator'></span>
          <StyledToggleButtonGroup>
            <MeshVisibleGroup />
          </StyledToggleButtonGroup>
          <span className='nm-ViewerToolbar-separator'></span>
          <ModelPickRadioGroup options={pickOptions} />
          <span className='nm-ViewerToolbar-separator'></span>
          <StyledToggleButtonGroup>
            <CommentSelected />
          </StyledToggleButtonGroup>
        </ul>
      </nav>
    </div>
  );
}
